home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / misc / emu / prlink_amiga.lha / prlink-0.8.0a / src / pramiga.c < prev    next >
C/C++ Source or Header  |  1995-04-25  |  9KB  |  361 lines

  1. #include "prtrans.h"
  2.  
  3. /*
  4.  * Note that for the Amiga only the pramiga cable is supported. This is
  5.  * because nobody would/could use the pc64 or 64net cables, because they
  6.  * are for compatibility with pc software. To make up for this, we can use
  7.  * the same prlink cable to its full potential by using all 8 data lines
  8.  * bidirectionally.
  9.  *
  10.  * To enable this, define PRLINK88 (in the Makefile below), and don't forget
  11.  * to set the cable type to prlink88 in the pet/vic/64 side programs as
  12.  * well.
  13.  */
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <unistd.h>
  17.  
  18. #include <exec/exec.h>
  19. #include <resources/misc.h>
  20. #include <hardware/cia.h>
  21. #include <clib/exec_protos.h>
  22. #include <clib/misc_protos.h>
  23.  
  24. /*
  25.  * The CIAs are volatile, otherwise the while loop waiting for ACK to
  26.  * change is "optimized".
  27.  */
  28. extern volatile struct CIA ciaa;
  29. extern volatile struct CIA ciab;
  30.  
  31. struct Library *MiscBase;
  32. static unsigned long MiscAllocated;
  33. static unsigned char ack;
  34. int        bounce;
  35. char        myname[] = "pramiga.c";
  36.  
  37. #define BUSY    (1 << CIAB_PRTRBUSY)    /* == 0x01 */
  38. #define POUT    (1 << CIAB_PRTRPOUT)    /* == 0x02 */
  39. #define NO_ASM    1
  40.  
  41. int
  42. prinit(void)
  43. {
  44.     atexit(prclose);
  45.  
  46.     MiscBase = OpenResource("misc.resource");
  47.     if (MiscBase == NULL) {
  48.     printf("Can't open misc.resource\n");
  49.     return -1;
  50.     } {
  51.     const char     *user;
  52.  
  53.     user = AllocMiscResource(MR_PARALLELPORT, myname);
  54.     if (user != NULL && user != myname) {
  55.         printf("Printer data lines already in use by %s.\n", user);
  56.         return -2;
  57.     }
  58.     MiscAllocated = 1 << MR_PARALLELPORT;
  59. #ifndef TRANSNIB
  60.     user = AllocMiscResource(MR_PARALLELBITS, myname);
  61.     if (user != NULL && user != myname) {
  62.         printf("Printer control lines already in use by %s.\n", user);
  63.         return -3;
  64.     }
  65.     MiscAllocated |= 1 << MR_PARALLELBITS;
  66. #endif
  67.     }
  68.  
  69. #ifndef TRANSNIB
  70.     /* turn POUT into output (BUSY is input) */
  71.     ciab.ciaddra = (ciab.ciaddra | POUT) & ~BUSY;
  72.     ciab.ciapra |= POUT;    /* and set it high */
  73.     ack = ciab.ciapra & BUSY;    /* get the current state of the BUSY line */
  74. #endif
  75.     ciaa.ciaddrb = 0xFF;    /* set all lines to output */
  76.     ciaa.ciaprb = 0xFF;     /* and high */
  77.  
  78.     return 0;
  79. }
  80.  
  81. void
  82. prclose(void)
  83. {
  84.     if (bounce != 0) {
  85.     printf("*** bounce, bounce! (%d times)\n", bounce);
  86.     bounce = 0;
  87.     }
  88. #ifndef TRANSNIB
  89.     if (MiscAllocated & (1 << MR_PARALLELBITS)) {
  90.     ciab.ciaddra &= ~POUT;    /* turn POUT back into input */
  91.     FreeMiscResource(MR_PARALLELBITS);
  92.     }
  93. #endif
  94.     if (MiscAllocated & (1 << MR_PARALLELPORT)) {
  95.     ciaa.ciaprb = 0xFF;
  96.     ciaa.ciaddrb = 0xFF;    /* set all data lines to output */
  97.     FreeMiscResource(MR_PARALLELPORT);
  98.     }
  99.     MiscAllocated = 0;
  100.     /* There is no CloseResource() function, really! */
  101. }
  102.  
  103. void
  104. output(unsigned char byte)
  105. {
  106.     send(&byte, 1);
  107. }
  108.  
  109. unsigned
  110. input(void)
  111. {
  112.     unsigned char   byte;
  113.  
  114.     receive(&byte, 1);
  115.     return byte;
  116. }
  117.  
  118. unsigned
  119. wait_input(void)
  120. {
  121. #ifdef TRANSNIB
  122.     while (ciaa.ciaprb & 0x40)    /* wait for DRDY to go low */
  123.     usleep (SLEEP_TIME);
  124.     ciaa.ciaddrb = 0x80;    /* set the bidirectional signals to input */
  125. #else
  126.     ciab.ciapra &= ~POUT;        /* drop the -FLAG to low */
  127.     while (ack == (BUSY & ciab.ciapra)) /* wait for BUSY to change */
  128.     usleep (SLEEP_TIME);
  129.     ciaa.ciaddrb = 0x00;    /* set the bidirectional signals to input */
  130. #endif
  131.     return input();
  132. }
  133.  
  134. #ifndef TRANSNIB
  135. void
  136. send(unsigned char *buffer, unsigned length)
  137. {
  138.     ciaa.ciaddrb = 0xFF;    /* set all lines to output */
  139.  
  140. #if defined(__GNUC__) && !NO_ASM
  141. /* INDENT OFF */
  142.     asm("
  143.     subql #1,%1
  144.     moveq #-1,d0
  145.     cmpl %1,d0
  146.     jeq .send
  147. .sbyteloop:
  148.     moveb %2@+,%4@
  149.     andb %6,%5@
  150. .sackloop:
  151.     moveb %5@,d0
  152.     andb %7,d0
  153.     cmpb %3,d0
  154.     jeq .sackloop
  155.  
  156.     orb %8,%5@
  157.     eorb %7,%3
  158.     dbra %1,.sbyteloop
  159.     clrw %1
  160.     subql #1,%1
  161.     jcc .sbyteloop
  162. .send:
  163.     " : "=d" (ack)              /* 0 output */
  164.       : "d" (length),           /* 1 input */
  165.     "a" (buffer),           /* 2 */
  166.     "0" (ack),              /* 3 */
  167.     "a" (&ciaa.ciaprb),     /* 4 */
  168.     "a" (&ciab.ciapra),     /* 5 */
  169.     "g" (~POUT),            /* 6 */
  170.     "g" (BUSY),             /* 7 */
  171.     "g" (POUT)              /* 8 */
  172.       : "d0"                    /* clobbered */
  173.     );
  174.     /* INDENT ON */
  175. #else
  176.     while (length--) {
  177.     ciaa.ciaprb = *buffer++;
  178.     ciab.ciapra &= ~POUT;    /* drop the -FLAG to low */
  179.     while (ack == (BUSY & ciab.ciapra));    /* wait for BUSY to change */
  180.     ciab.ciapra |= POUT;    /* raise -FLAG again */
  181.     ack ^= BUSY;        /* store the new state of -BUSY */
  182.     }
  183. #endif
  184. }
  185.  
  186. #ifdef PRLINK88
  187. void
  188. receive(unsigned char *buffer, unsigned length)
  189. {
  190.  
  191.     ciaa.ciaddrb = 0x00;    /* set the bidirectional signals to input */
  192.  
  193. #if defined(__GNUC__) && !NO_ASM
  194. /* INDENT OFF */
  195.     asm("
  196.     subql #1,%1
  197.     moveq #-1,d0
  198.     cmpl %1,d0
  199.     jeq .rend
  200.  
  201. .rbyteloop:
  202.     andb %6,%5@
  203. .rackloop:
  204.     moveb %5@,d0
  205.     andb %7,d0
  206.     cmpb %3,d0
  207.     jeq .rackloop
  208.  
  209.     orb %8,%5@
  210.     moveb %4@,%2@+
  211.  
  212.     eorb %7,%3
  213.     dbra %1,.rbyteloop
  214.     clrw %1
  215.     subql #1,%1
  216.     jcc .rbyteloop
  217.  
  218. .rend:
  219.     " : "=d" (ack)              /* 0 output */
  220.       : "d" (length),           /* 1 input */
  221.     "a" (buffer),           /* 2 */
  222.     "0" (ack),              /* 3 */
  223.     "a" (&ciaa.ciaprb),     /* 4 data */
  224.     "a" (&ciab.ciapra),     /* 5 ctl */
  225.     "g" (~POUT),            /* 6 */
  226.     "g" (BUSY),             /* 7 */
  227.     "g" (POUT)              /* 8 */
  228.       : "d0"                    /* clobbered */
  229.     );
  230.     /* INDENT ON */
  231. #else
  232.     while (length--) {
  233.     ciab.ciapra &= ~POUT;    /* drop the -FLAG to low */
  234. bounced:
  235.     while (ack == (BUSY & ciab.ciapra));    /* wait for BUSY to change */
  236.     *buffer++ = ciaa.ciaprb;/* read the byte */
  237.     ciab.ciapra |= POUT;    /* raise -FLAG again */
  238.     /* debounce */
  239.     {
  240.         int         bouncecount;
  241.  
  242.         for (bouncecount = 0; bouncecount < 2; bouncecount++) {
  243.         if (ack == (BUSY & ciab.ciapra) || buffer[-1] != ciaa.ciaprb) {
  244.             buffer--;
  245.             bounce++;
  246.             goto bounced;
  247.         }
  248.         }
  249.     }
  250.     ack ^= BUSY;        /* store the new state of -BUSY */
  251.     }
  252. #endif
  253. }
  254.  
  255. #else                /* not PRLINK88 */
  256.  
  257. void
  258. receive(unsigned char *buffer, unsigned length)
  259. {
  260.     register unsigned char data;
  261.  
  262.     ciaa.ciaddrb = 0x00;    /* set all signals to input */
  263.  
  264.     while (length--) {
  265.     ciab.ciapra &= ~POUT;    /* drop the -FLAG to low */
  266.     while (ack == (BUSY & ciab.ciapra));    /* wait for BUSY to change */
  267.     ciab.ciapra |= POUT;    /* raise -FLAG again */
  268.     data = ciaa.ciaprb & 0x0f;    /* read the low nybble */
  269.  
  270.     ciab.ciapra &= ~POUT;    /* drop the -FLAG to low */
  271.     while (ack != (BUSY & ciab.ciapra));    /* wait for BUSY to change */
  272.  
  273.     ciab.ciapra |= POUT;    /* raise -FLAG again */
  274.     data |= (ciaa.ciaprb & 0x0f) << 4;    /* read the high nybble */
  275.  
  276.     *buffer++ = data;
  277.     }
  278. }
  279.  
  280. #endif                /* PRLINK88 */
  281.  
  282. #else                /* TRANSNIB */
  283.  
  284. /*-
  285.  *  TransNib is a cable that has only 6 bits connected:
  286.  *
  287.  *  0-3:    data i/o
  288.  *  6:        handshake in
  289.  *  7:        handshake out
  290.  *
  291.  *  Because the cable is straight-through, bits 6 and 7 are swapped
  292.  *  at the PET/C-64/VIC-20 side.
  293.  *
  294.  *  The protocol is provided for people who made a cable for
  295.  *  TransNib V1.00 Devised by Matt Francis (m.p.francis@newcastle.ac.uk).
  296.  *  Because the cable is a subset of the prlink cable it will also work
  297.  *  with that.
  298.  *
  299.  *  Note that this protocol is not compatible with the TransNib programs!
  300. -*/
  301.  
  302. void
  303. send(unsigned char *buffer, unsigned length)
  304. {
  305.     register unsigned char data;
  306.  
  307.     /*
  308.      * $40 is DRCV (input), $80 is DRDY (output) Note that the names are
  309.      * swapped from receiving but the data direction isn't!
  310.      */
  311.     ciaa.ciaddrb = 0x8f;    /* set the bidirectional signals to output */
  312.  
  313.     while (length--) {
  314.     register unsigned char nibble;
  315.  
  316.     data = *buffer++;
  317.     nibble = data >> 4;
  318.  
  319.     ciaa.ciaprb = nibble;    /* set DRDY low */
  320.     while (ciaa.ciaprb & 0x40);    /* wait for DRCV to go low */
  321.     ciaa.ciaprb = nibble | 0x80;    /* set DRDY high */
  322.     while (!(ciaa.ciaprb & 0x40));    /* wait for DRCV to go high */
  323.  
  324.     nibble = data & 0x0F;
  325.  
  326.     ciaa.ciaprb = nibble;    /* set DRDY low */
  327.     while (ciaa.ciaprb & 0x40);    /* wait for DRCV to go low */
  328.     ciaa.ciaprb = nibble | 0x80;    /* set DRDY high */
  329.     while (!(ciaa.ciaprb & 0x40));    /* wait for DRCV to go high */
  330.     }
  331. }
  332.  
  333. void
  334. receive(unsigned char *buffer, unsigned length)
  335. {
  336.     register unsigned char data;
  337.  
  338.     /*
  339.      * $80 is DRCV (output), $40 is DRDY (input)
  340.      */
  341.     ciaa.ciaddrb = 0x80;    /* set the bidirectional signals to input */
  342.  
  343.     while (length--) {
  344.     while (ciaa.ciaprb & 0x40);    /* wait for DRDY to go low */
  345.     data = (ciaa.ciaprb & 0x0f) << 4;    /* read the high nybble */
  346.     ciaa.ciaprb = data & ~0x80;    /* set DRCV low */
  347.     while (!(ciaa.ciaprb & 0x40));    /* wait for DRDY to go high */
  348.     ciaa.ciaprb = data | 0x80;    /* set DRCV high */
  349.  
  350.     while (ciaa.ciaprb & 0x40);    /* wait for DRDY to go low */
  351.     data |= ciaa.ciaprb & 0x0f;    /* read the low nybble */
  352.     ciaa.ciaprb = data & ~0x80;    /* set DRCV low */
  353.     while (!(ciaa.ciaprb & 0x40));    /* wait for DRDY to go high */
  354.     ciaa.ciaprb = data | 0x80;    /* set DRCV high */
  355.  
  356.     *buffer++ = data;
  357.     }
  358. }
  359.  
  360. #endif                /* TRANSNIB */
  361.